package com.me.bbs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.me.bbs.common.AdminType;
import com.me.bbs.common.AuthUtils;
import com.me.bbs.common.SessionUtils;
import com.me.bbs.dto.PostDTO;
import com.me.bbs.entity.*;
import com.me.bbs.exceptions.NotExistException;
import com.me.bbs.mapper.PostMapper;
import com.me.bbs.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lm
 * @since 2023-01-09
 */
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements IPostService {
    @Resource
    IUserService userService;
    @Resource
    IForumService forumService;
    @Resource
    PostMapper postMapper;
    @Resource
    IViewRecordService viewRecordService;
    @Resource
    IPostLikeService postLikeService;
    @Resource
    ICollectionService collectionService;
    @Resource
    IUserFollowingService userFollowingService;
    @Resource
    ICommentService commentService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createPost(Post post) throws Exception {
        AuthUtils.checkBan(post.getForum());
        boolean isSaveOk = this.save(post);
        if (!isSaveOk)
            throw new Exception("保存post失败");
        LambdaUpdateWrapper<User> userLambdaUpdateWrapper
                = new LambdaUpdateWrapper<>();
        userLambdaUpdateWrapper.eq(User::getUserId, post.getAuthor())
                .setSql("post_count = post_count + 1");
        boolean isUserUpdate = userService.update(userLambdaUpdateWrapper);
        if (!isUserUpdate)
            throw new Exception("保存post失败");
        LambdaUpdateWrapper<Forum> forumLambdaUpdateWrapper
                = new LambdaUpdateWrapper<>();
        forumLambdaUpdateWrapper.eq(Forum::getId, post.getForum())
                .setSql("post_count = post_count + 1");
        boolean isForumUpdate = forumService.update(forumLambdaUpdateWrapper);
        if (!isForumUpdate)
            throw new Exception("保存post失败");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PostDTO getPostDto(Long id) {
        PostDTO postDTO = postMapper.selectPostDtoById(id);
        if(postDTO == null)
            throw new NotExistException();
        Long uid = (Long) SessionUtils
                .getAttribute("user");
        this.lambdaUpdate()
                .eq(Post::getPostId,id)
                .setSql("view_count = view_count + 1")
                .update();
        if (uid == null)
            return postDTO;
        //是否关注用户
        boolean isFollowed = userFollowingService.lambdaQuery().eq(UserFollowing::getUser, uid)
                .eq(UserFollowing::getFollowedUser, postDTO.getAuthor().getUserId())
                .exists();
        postDTO.getAuthor().setIsFollowed(isFollowed);
        //是否收藏
        boolean isCollected = collectionService.lambdaQuery()
                .eq(PostCollection::getPost, id)
                .eq(PostCollection::getUser, uid)
                .exists();
        postDTO.setIsCollected(isCollected);
        //是否点赞
        boolean isLike = postLikeService.lambdaQuery()
                .eq(PostLike::getPost, id)
                .eq(PostLike::getUser, uid)
                .exists();
        postDTO.setIsLike(isLike);
        //更新或者新增浏览器记录
        ViewRecord vr = viewRecordService.lambdaQuery().eq(ViewRecord::getPost, id)
                .eq(ViewRecord::getUser, uid)
                .one();
        if(vr == null) {
            vr = new ViewRecord();
            vr.setPost(id);
            vr.setUser(uid);
        } else
            vr.setViewTime(null);
        viewRecordService.saveOrUpdate(vr);
        return postDTO;
    }

    @Override
    public Page<PostDTO> getPostList(Page<PostDTO> dtoPage, LambdaQueryWrapper<Post> wrapper) {
        return postMapper.listPostDto(dtoPage, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletePost(Long postId) {
        Post p = this.lambdaQuery().eq(Post::getPostId, postId).one();
        if(p == null)
            return false;
        //鉴权
        Long forumId = p.getForum();
        Long uid = (Long) SessionUtils.getAttribute("user");
        if(!Objects.equals(uid, p.getAuthor()))
            AuthUtils.checkAdmin(AdminType.ADMIN, forumId);
        //用户帖子数量和吧帖子数量减1
        forumService.lambdaUpdate().eq(Forum::getId, p.getForum())
                .setSql("post_count = post_count - 1").update();
        userService.lambdaUpdate().eq(User::getUserId, p.getAuthor())
                .setSql("post_count = post_count - 1").update();
        //删除文章相关表内容
        postLikeService.lambdaUpdate().eq(PostLike::getPost, postId).remove();
        commentService.lambdaUpdate().eq(Comment::getPost, postId).remove();
        this.lambdaUpdate().eq(Post::getPostId,postId).remove();
        return true;
    }
}
